package com.qumitech.visualnovel.component.exception;

import com.qumitech.visualnovel.model.common.BaseRsp;
import com.qumitech.visualnovel.model.common.ErrRsp;
import com.qumitech.visualnovel.model.common.ResultEnum;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpStatus;
import org.springframework.validation.BindException;
import org.springframework.validation.FieldError;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;

import java.io.IOException;

@ControllerAdvice
public class GlobalExceptionHandler {
    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    @ExceptionHandler(BusinessException.class)
    public @ResponseBody
    ErrRsp handleBusinessException(Exception ex) {

        if (ex instanceof BusinessException) {
            ResultEnum resultEnum = ((BusinessException)ex).getResultEnum();
            ErrRsp rsp = new ErrRsp(resultEnum.getState(), resultEnum.getMsg());

            return rsp;
        }

        return null;
    }

    @ExceptionHandler(BindException.class)
    public @ResponseBody
    ErrRsp handleBindException(BindException ex) {
        StringBuilder sb = new StringBuilder();
        for (FieldError fieldError : ex.getFieldErrors()) {
            sb.append(fieldError.getDefaultMessage());
        }

        return new ErrRsp(400, sb.toString());
    }

    @ExceptionHandler(HttpRequestMethodNotSupportedException.class)
    public @ResponseBody
    BaseRsp handleMethodNotSupportedException(HttpRequestMethodNotSupportedException ex) {

        return new BaseRsp(450, ex.getMessage());
    }

    @ExceptionHandler(MissingServletRequestParameterException.class)
    public @ResponseBody
    ErrRsp handleMethodParameterException(MissingServletRequestParameterException ex) {
        String message  = ex.getMessage();
        return new ErrRsp(406, message);
    }

    @ExceptionHandler(MethodArgumentNotValidException.class)
    public @ResponseBody
    ErrRsp handleMethodArgumentNotValidException(MethodArgumentNotValidException ex) {
        String message  = ex.getMessage();
        return new ErrRsp(406, message);
    }

    /**
     * 处理Broken pipe
     * @param e
     * @return
     */
    @ExceptionHandler(IOException.class)
    @ResponseStatus(HttpStatus.SERVICE_UNAVAILABLE)
    public Object exceptionHandler(IOException e) {
        if (StringUtils.containsIgnoreCase(ExceptionUtils.getRootCauseMessage(e), "Broken pipe")) {
            return null;
        } else {
            return new HttpEntity<>(e.getMessage());
        }
    }
}
